<?php

namespace july\julyadmin\builder\forms;

use july\julyadmin\builder\FormBase;

/**
 * 表单JsTree组件
 */
class JsTree extends FormBase
{
    /**
     * 添加组件
     * @Author
     * @DateTime 2023-07-16T12:14:26+0800
     * @param    string                   $field 字段
     * @param    string                   $label 名称
     * @return this
     */
    public function __construct($field = '', $label = '')
    {
        $form          = new \stdClass();
        $form->type    = 'js-tree';
        $form->field   = $field;
        $form->label   = $label;
        $form->open    = 'true';
        $form->plugins = ["dnd", "types"];
        $form->options = [];
        $form->dataUrl = '';
        $form->style   = '';

        $form->help     = '';
        $form->tips     = ['tips' => '', 'direction' => 2, 'time' => 0, 'background' => '#000000'];
        $form->required = false;
        //内容
        $form->value   = '';
        $form->default = '';
        $this->form    = $form;

        $this->js = '
        <script type="text/javascript" src="/static/assets/admin/js/jstree/jstree.min.js"></script>
        ';
        $this->css = '
        <link rel="stylesheet" type="text/css" href="/static/assets/admin/js/jstree/style.min.css" rel="stylesheet">
        <link rel="stylesheet" type="text/css" href="/static/assets/admin/js/jstree/mystyle.css" rel="stylesheet">
                ';
        return $this;
    }

    /**
     * 是否展开
     * @Author
     * @DateTime 2023-07-16T12:35:20+0800
     * @param    boolean                  $is_open 是否展开,true,false
     */
    public function setOpen($is_open = true)
    {
        $this->form->open = $is_open ? 'true' : 'false';
        return $this;
    }

    /**
     * 是否显示复选框
     * @Author
     * @DateTime 2023-07-16T12:34:55+0800
     * @param    boolean                  $show 是否显示复选框,true,false
     * @return   this
     */
    public function showCheckbox($show = true)
    {
        if ($show) {
            $this->form->plugins[] = "checkbox";
        }
        return $this;
    }

    /**
     * 设置树形数据请求地址
     * @Author
     * @DateTime 2023-07-16T12:34:31+0800
     * @param    string                   $url 请求地址
     * @return   this
     */
    public function dataUrl($url = "")
    {
        $this->form->dataUrl = is_string($url) ? $url : (string) $url;
        return $this;
    }

    /**
     * 设置列表 数据
     * @Author
     * @DateTime 2023-07-16T12:25:21+0800
     * @param    array                   $options 列表数据，参考jstree文档
     * @return   this
     */
    public function options($options = [])
    {
        $this->form->options = $options;
        return $this;
    }

    /**
     * 设置style
     * @Author
     * @DateTime 2023-07-16T12:19:05+0800
     * @param    string                   $style 样式，直接写css
     * @return   this
     */
    public function style($style = '')
    {
        $this->form->style = $style;
        return $this;
    }

    /**
     * 渲染组件
     * @Author
     * @DateTime 2023-07-16T12:22:46+0800
     * @return   array
     */
    public function render()
    {
        $this->form->value = $this->form->default;
        $required_html     = $this->form->required && !$this->isView && !$this->isView ? ' <font style="color:red;font-weight:bold;font-size:20px;vertical-align:-webkit-baseline-middle;">*</font>' : '';

        //处理tips
        $tips = '';
        if ($this->form->tips['tips']) {
            $tips = '<font class="form-tips-icon"><i class="mdi mdi-information-outline" tips="' . $this->form->tips['tips'] . '" direction="' . $this->form->tips['direction'] . '" time="' . $this->form->tips['time'] . '" background="' . $this->form->tips['background'] . '" onclick="showTips(this)"></i></font>';
        }

        $this->html .= <<< EOT

        <div class="row ps-0 pe-0 ms-0 me-0 mt-3 mb-3 col-md-{$this->colWidth}">
            <label class="col-sm-{$this->labelWidth} col-form-label pe-2 col-form-label-sm text-sm-end text-md-end text-lg-end text-xl-end">
                {$tips}{$this->form->label}
                {$required_html}
            </label>

EOT;
        $input_html = "";
        $input_html .= <<<EOT

        <div class="mt-2 mb-2">
            <div id="form-jstree-{$this->form->field}" name="{$this->form->field}" style="{$this->form->style}"></div>
        </div>

EOT;
        //处理help
        if ($this->form->help) {
            $input_html .= <<<EOT

            <div class="form-help form-text">
                <i class="mdi mdi-information-outline"></i>
                <font>{$this->form->help}</font>
            </div>

EOT;
        }

        $this->html .= <<< EOT

            <div class="col-sm-{$this->inputWidth}">
                {$input_html}
            </div>
        </div>

EOT;

        $plugins              = json_encode($this->form->plugins, JSON_UNESCAPED_SLASHES);
        $this->form->required = $this->form->required ? 'required' : '';
        $field                = md5("jstree-{$this->form->field}");
        $this->script .= <<<EOT

            <script>
                //递归禁用开启
                function jsTreeDisabled{$field}(array,disabled){
                    array.forEach((item,index) => {
                        item.checked = false;
                        if(item.hasOwnProperty('state')){
                            array[index].state.disabled = disabled;
                        }else{
                            array[index].state = {disabled:disabled};
                        }
                        if(item.hasOwnProperty('children') && item.children){
                            jsTreeDisabled{$field}(item.children,disabled);
                        }
                    });
                    return array;
                }

                //递归展开关闭
                function jsTreeExpandAllNodes{$field}(array,open){
                    array.forEach((item,index) => {
                        item.checked = false;
                        if(item.hasOwnProperty('state')){
                            array[index].state.opened = open;
                        }else{
                            array[index].state = {opened:open};
                        }
                        if(item.hasOwnProperty('children') && item.children){
                            this.jsTreeExpandAllNodes{$field}(item.children,open);
                        }
                    });
                    return array;
                }
            </script>

EOT;
        $options = json_encode($this->form->options);
        if (in_array("checkbox", $this->form->plugins)) {
            //多选
            if (!is_array($this->form->value)) {
                $this->form->value = explode(",", $this->form->value);
            }
            $this->form->value = json_encode($this->form->value, JSON_UNESCAPED_SLASHES);
        } else {
            //单选
            if (is_array($this->form->value)) {
                throw new \Exception("当没有调用->showCheckbox(true)开启复选框时,设置的值只能是字符串，如：1");
            }
        }
        if ($this->form->options && !$this->form->dataUrl) {
            $isView = $this->isView || $this->readonly ? 'true' : 'false';
            $this->script .= <<<EOT
            <script>
                var options = {$options};
                options = jsTreeDisabled{$field}(options,'{$isView}'=='true'?true:false);
                options = jsTreeExpandAllNodes{$field}(options,{$this->form->open});
                console.log(options);
                $('#form-jstree-{$this->form->field}').jstree({
                    'core' : {
                        'animation' : 0,
                        'check_callback' : true,
                        'force_text' : true,
                        'themes' : {
                            'responsive': false
                        },
                        'data' : options
                    },
                    "types" : {
                        'default' : {
                            'icon' : 'mdi mdi-folder-outline'
                        },
                        'file' : {
                            'icon' : 'mdi mdi-file-outline'
                        }
                    },
                    "plugins" : {$plugins}
                });
                $('#form-jstree-{$this->form->field}').on('changed.jstree', function (e, data) {
                    //选中节点改变事件
                    if({$plugins}.includes("checkbox")){
                        var result = $('#form-jstree-{$this->form->field}').jstree('get_selected').join(',');
                    }else{
                        var result = data.node.id;
                    }
                    setTimeout(function(){
                        $('#form-{$this->form->field}').val(result);
                    },50);

                });
                //加载完成事件
                $('#form-jstree-{$this->form->field}').on('ready.jstree', function(event, obj) {
                    //设置选中项
                    if({$plugins}.includes("checkbox")){
                        //多选
                        $('#form-jstree-{$this->form->field}').jstree().check_node({$this->form->value});
                    }else{
                        //单选
                        $('#form-jstree-{$this->form->field}').jstree('select_node', '{$this->form->value}' , false);
                    }
EOT;
            if (!$this->isView) {
                $this->script .= <<<EOT
                    //创建一个隐藏的input，不然提交没数据，表单验证也不行
                    $('#form-jstree-{$this->form->field}').append("<input type='text' id='form-{$this->form->field}' name='{$this->form->field}' {$this->readonly} {$this->form->required} style='height:1px;position:absolute;width: 1px;margin-top:-81px;margin-left:35px;z-index:-1;'/>");
EOT;
            }
            $this->script .= <<<EOT

                });
            </script>
EOT;
        } else if (!$this->form->options && $this->form->dataUrl) {
            $isView = $this->isView ? 'true' : 'false';
            $this->script .= <<<EOT
            <script>
                window.loading  = layer.load(2,{shade:0});
                $.ajax({
                    type:'GET',
                    url:'{$this->form->dataUrl}',
                    data:data,
                    dataType:'json',
                    success:function(res) {
                        layer.close(window.loading);
                        if(res.hasOwnProperty("code") && res.code==1){
                            var options = res.data;
                            options = jsTreeDisabled{$field}(options,'{$isView}'=='true'?true:false);
                            options = jsTreeExpandAllNodes{$field}{$field}(options,{$this->form->open});
                            options.map((item,index)=>{
                                if(!item.hasOwnProperty("state") || !item.state.hasOwnProperty("opened")){
                                    options[index].state = {
                                        "opened":{$this->form->open}
                                    }
                                }
                            });

                            $('#form-jstree-{$this->form->field}').jstree({
                                'core' : {
                                    'animation' : 0,
                                    'check_callback' : true,
                                    'force_text' : true,
                                    'themes' : {
                                        'responsive': false
                                    },
                                    'data' : options
                                },
                                "types" : {
                                    'default' : {
                                        'icon' : 'mdi mdi-folder-outline'
                                    },
                                    'file' : {
                                        'icon' : 'mdi mdi-file-outline'
                                    }
                                },
                                "plugins" : {$plugins}
                            });
                            $('#form-jstree-{$this->form->field}').on('changed.jstree', function (e, data) {
                                //选中节点改变事件
                                var result = [];
                                if({$plugins}.includes("checkbox")){
                                    var result = $('#form-jstree-{$this->form->field}').jstree('get_selected').join(',');
                                }else{
                                    var result = data.node.id;
                                }
                                setTimeout(function(){
                                    $('#form-{$this->form->field}').val(result);
                                },50);
                            });
                            //加载完成事件
                            $('#form-jstree-{$this->form->field}').on('ready.jstree', function(event, obj) {
                                //设置选中项
                                if({$plugins}.includes("checkbox")){
                                    //多选
                                    $('#form-jstree-{$this->form->field}').jstree().check_node({$this->form->value});
                                }else{
                                    //单选
                                    $('#form-jstree-{$this->form->field}').jstree('select_node', '{$this->form->value}' , false);
                                }
                                //创建一个隐藏的input，不然提交没数据，表单验证也不行
                                $('#form-jstree-{$this->form->field}').append("<input type='text' id='form-{$this->form->field}' name='{$this->form->field}' {$this->readonly} {$this->form->required} style='height:1px;position:absolute;width: 1px;margin-top:-81px;margin-left:35px;z-index:-1;'/>");
                                    });
                        }else{
                            layer.msg('{$this->form->label}加载失败！',{
                                icon:5,
                                time:2000,
                                shade:[0.6,'#000',false]
                            });
                        }
                    },
                    error:function(res){
                        layer.close(window.loading);
                        layer.msg(JSON.stringify(res),{
                            icon:5,
                            time:2000,
                            shade:[0.6,'#000',false]
                        });
                    }
                });
            </script>
EOT;
        }

        $result = ['html' => $this->html, 'script' => $this->script, 'js' => $this->js, 'css' => $this->css];
        return $result;
    }
}
